x86, hvm: Config option to allow vmxassist to be disabled.
authorKeir Fraser <keir@xensource.com>
Sat, 24 Nov 2007 13:23:22 +0000 (13:23 +0000)
committerKeir Fraser <keir@xensource.com>
Sat, 24 Nov 2007 13:23:22 +0000 (13:23 +0000)
hvmloader is modified to dynamically detect this, allowing possibility
of optional full vmxassist replacement in 3.2 stable branch in future.
Currently 'vmxassist=y' is not much use since no replacement is
implemented.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
tools/firmware/hvmloader/hvmloader.c
xen/arch/x86/Rules.mk
xen/arch/x86/hvm/vmx/vmx.c
xen/arch/x86/hvm/vpic.c
xen/include/asm-x86/hvm/vmx/vmcs.h

index 17209e1f5bbcd7586af2ba454e7a5ba1ffe617a1..a9c59bd0298c6cdec50c567a4bf5a8bd197df9d2 100644 (file)
@@ -40,6 +40,7 @@ asm(
     "    cli                         \n"
     "    movl $stack_top,%esp        \n"
     "    movl %esp,%ebp              \n"
+    "    movl %eax,initial_eax       \n"
     "    call main                   \n"
     /* Relocate real-mode trampoline to 0x0. */
     "    mov  $trampoline_start,%esi \n"
@@ -97,6 +98,8 @@ asm(
     "stack_top:                      \n"
     );
 
+static unsigned int initial_eax;
+
 void create_mp_tables(void);
 int hvm_write_smbios_tables(void);
 
@@ -121,6 +124,12 @@ check_amd(void)
     return __builtin_memcmp(id, "AuthenticAMD", 12) == 0;
 }
 
+static int
+use_vmxassist(void)
+{
+    return !check_amd() && !initial_eax;
+}
+
 static void
 wrmsr(uint32_t idx, uint64_t v)
 {
@@ -407,7 +416,7 @@ int main(void)
         printf(" %05x-%05x: Etherboot ROM\n",
                ETHERBOOT_PHYSICAL_ADDRESS,
                ETHERBOOT_PHYSICAL_ADDRESS + etherboot_sz - 1);
-    if ( !check_amd() )
+    if ( use_vmxassist() )
         printf(" %05x-%05x: VMXAssist\n",
                VMXASSIST_PHYSICAL_ADDRESS,
                VMXASSIST_PHYSICAL_ADDRESS + sizeof(vmxassist) - 1);
@@ -424,7 +433,7 @@ int main(void)
                ROMBIOS_PHYSICAL_ADDRESS,
                ROMBIOS_PHYSICAL_ADDRESS + rombios_sz - 1);
 
-    if ( !check_amd() )
+    if ( use_vmxassist() )
     {
         printf("Loading VMXAssist ...\n");
         memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS,
index cbc2f1dadc8bdd64e312de23da8f18d35c0cff7a..1925c2f1b98675ffd7c31acdfb23ebc806eca7ba 100644 (file)
@@ -11,6 +11,11 @@ xenoprof := y
 #
 pae ?= n
 supervisor_mode_kernel ?= n
+vmxassist ?= y
+
+ifeq ($(vmxassist),y)
+CFLAGS += -DVMXASSIST
+endif
 
 # Solaris grabs stdarg.h and friends from the system include directory.
 ifneq ($(XEN_OS),SunOS)
index 21f592a7ae74af2fca7388119119551e0e38eca7..2bf8a38bcb32bcc9fed3a8ead7d132783453c2e9 100644 (file)
@@ -92,6 +92,11 @@ static int vmx_vcpu_initialise(struct vcpu *v)
 
     vmx_install_vlapic_mapping(v);
 
+#ifndef VMXASSIST
+    if ( v->vcpu_id == 0 )
+        v->arch.guest_context.user_regs.eax = 1;
+#endif
+
     return 0;
 }
 
@@ -701,7 +706,9 @@ static void vmx_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
     v->arch.hvm_vmx.shadow_gs = data->shadow_gs;
 #endif
 
+#ifdef VMXASSIST
     v->arch.hvm_vmx.vmxassist_enabled = !(data->cr0 & X86_CR0_PE);
+#endif
 
     hvm_set_guest_time(v, data->tsc);
 
@@ -961,9 +968,11 @@ static void vmx_init_ap_context(
     struct vcpu_guest_context *ctxt, int vcpuid, int trampoline_vector)
 {
     memset(ctxt, 0, sizeof(*ctxt));
+#ifdef VMXASSIST
     ctxt->user_regs.eip = VMXASSIST_BASE;
     ctxt->user_regs.edx = vcpuid;
     ctxt->user_regs.ebx = trampoline_vector;
+#endif
 }
 
 void do_nmi(struct cpu_user_regs *);
@@ -1045,7 +1054,10 @@ static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr)
 
         v->arch.hvm_vcpu.hw_cr[0] =
             v->arch.hvm_vcpu.guest_cr[0] |
-            X86_CR0_PE | X86_CR0_NE | X86_CR0_PG | X86_CR0_WP;
+            X86_CR0_NE | X86_CR0_PG | X86_CR0_WP;
+#ifdef VMXASSIST
+        v->arch.hvm_vcpu.hw_cr[0] |= X86_CR0_PE;
+#endif
         __vmwrite(GUEST_CR0, v->arch.hvm_vcpu.hw_cr[0]);
         __vmwrite(CR0_READ_SHADOW, v->arch.hvm_vcpu.guest_cr[0]);
         break;
@@ -1246,6 +1258,7 @@ static void vmx_do_cpuid(struct cpu_user_regs *regs)
     unsigned int input = regs->eax;
     unsigned int eax, ebx, ecx, edx;
 
+#ifdef VMXASSIST
     if ( input == 0x40000003 )
     {
         /*
@@ -1280,6 +1293,7 @@ static void vmx_do_cpuid(struct cpu_user_regs *regs)
         regs->edx = (u32)(value >> 32);
         return;
     }
+#endif
 
     hvm_cpuid(input, &eax, &ebx, &ecx, &edx);
 
@@ -1816,6 +1830,8 @@ static void vmx_io_instruction(unsigned long exit_qualification,
     }
 }
 
+#ifdef VMXASSIST
+
 static void vmx_world_save(struct vcpu *v, struct vmx_assist_context *c)
 {
     struct cpu_user_regs *regs = guest_cpu_user_regs();
@@ -2058,6 +2074,19 @@ static int vmx_set_cr0(unsigned long value)
     return 1;
 }
 
+#else /* !defined(VMXASSIST) */
+
+#define vmx_set_cr0(v) hvm_set_cr0(v)
+
+static int vmx_realmode(struct cpu_user_regs *regs)
+{
+    gdprintk(XENLOG_ERR, "Attempt to enter real mode on VCPU %d\n",
+             current->vcpu_id);
+    return -EINVAL;
+}
+
+#endif
+
 #define CASE_SET_REG(REG, reg)      \
     case REG_ ## REG: regs->reg = value; break
 #define CASE_GET_REG(REG, reg)      \
@@ -2677,9 +2706,16 @@ static void vmx_failed_vmentry(unsigned int exit_reason,
                                struct cpu_user_regs *regs)
 {
     unsigned int failed_vmentry_reason = (uint16_t)exit_reason;
-    unsigned long exit_qualification;
+    unsigned long exit_qualification = __vmread(EXIT_QUALIFICATION);
+
+#ifndef VMXASSIST
+    if ( (failed_vmentry_reason == EXIT_REASON_INVALID_GUEST_STATE) &&
+         (exit_qualification == 0) &&
+         !(current->arch.hvm_vcpu.hw_cr[0] & X86_CR0_PE) &&
+         (vmx_realmode(regs) == 0) )
+        return;
+#endif
 
-    exit_qualification = __vmread(EXIT_QUALIFICATION);
     printk("Failed vm entry (exit reason 0x%x) ", exit_reason);
     switch ( failed_vmentry_reason )
     {
index 4a3fc5ae5a68585dea93cb4d17c4f5d5977284b3..ab57cda5fbc7d0cf5920a8ba7e9b5eebf5c63e5b 100644 (file)
@@ -271,7 +271,7 @@ static void vpic_ioport_write(
             vpic->imr = val;
             break;
         case 1:
-#if 1 /* Delete me when vmxassist is retired. */
+#ifdef VMXASSIST
             /* Which mode is irqbase programmed in? */
             current->arch.hvm_vmx.irqbase_mode =
                 current->arch.hvm_vmx.vmxassist_enabled;
index 515eafdfbabc9469d44cdc178f0efd9fcd1c7022..0654264b468301d8208fbe09e4f5dee75e8f4bd8 100644 (file)
 #include <asm/config.h>
 #include <asm/hvm/io.h>
 #include <asm/hvm/vmx/cpu.h>
+
+#ifdef VMXASSIST
 #include <public/hvm/vmx_assist.h>
+#endif
 
 extern void start_vmx(void);
 extern void vmcs_dump_vcpu(void);
@@ -85,10 +88,11 @@ struct arch_vmx_struct {
     unsigned int         host_msr_count;
     struct vmx_msr_entry *host_msr_area;
 
-    /* Following fields are all specific to vmxassist. */
+#ifdef VMXASSIST
     unsigned long        vmxassist_enabled:1;
     unsigned long        irqbase_mode:1;
     unsigned char        pm_irqbase[2];
+#endif
 };
 
 int vmx_create_vmcs(struct vcpu *v);